<template>
  <a-modal
    :open="visible"
    :title="`角色权限分配`"
    width="1300px"
    :confirm-loading="loading"
    @ok="handleSave"
    @cancel="handleCancel"
  >
    <div class="role-permission-container">
      <div class="permission-layout">
        <!-- 左侧：基本信息 -->
        <div class="system-list">
          <div class="section-title">基本信息</div>
          <div class="system-items">应用：{{ roleData.appName }}</div>
          <div class="system-items">角色：{{ roleData.name }}</div>
        </div>

        <!-- 中间：功能权限分配 -->
        <div class="permission-assignment">
          <div class="section-header">
            <div class="section-title">功能权限分配</div>
            <div class="permission-stats">
              <span class="stats-item">
                <span class="stats-label">已选择:</span>
                <span class="stats-value">{{ checkedKeys.length }}</span>
              </span>
              <span class="stats-item">
                <span class="stats-label">总计:</span>
                <span class="stats-value">{{ getTotalPermissionCount() }}</span>
              </span>
            </div>
          </div>

          <a-spin :spinning="treeLoading">
            <div class="tree-toolbar">
              <div class="tree-actions">
                <a-button
                  type="primary"
                  ghost
                  size="small"
                  @click="expandAll"
                  class="action-btn"
                >
                  <template #icon><fullscreen-outlined /></template>
                  展开全部
                </a-button>
                <a-button
                  type="primary"
                  ghost
                  size="small"
                  @click="collapseAll"
                  class="action-btn"
                >
                  <template #icon><fullscreen-exit-outlined /></template>
                  收起全部
                </a-button>

                <a-button
                  type="primary"
                  size="small"
                  @click="checkAll"
                  class="action-btn check-all"
                >
                  <template #icon><check-outlined /></template>
                  全选
                </a-button>
                <a-button
                  size="small"
                  @click="uncheckAll"
                  class="action-btn uncheck-all"
                >
                  <template #icon><close-outlined /></template>
                  取消全选
                </a-button>
              </div>
            </div>

            <div class="tree-container">
              <a-tree
                v-if="treeData.length > 0"
                ref="treeRef"
                v-model:checkedKeys="checkedKeys"
                v-model:expandedKeys="expandedKeys"
                v-model:selectedKeys="selectedKeys"
                :tree-data="treeData"
                :field-names="{
                  children: 'children',
                  title: 'name',
                  key: 'code',
                }"
                checkable
                :check-strictly="false"
                :height="500"
                show-line
                :block-node="true"
                class="permission-tree"
                @select="handleNodeSelect"
                @check="handleCheck"
              >
                <template #title="{ name, type, code }">
                  <div class="tree-node">
                    <div class="node-content">
                      <div
                        class="node-icon"
                        :class="`icon-${type?.toLowerCase()}`"
                      >
                        <folder-open-outlined v-if="type === 'DIRECTORY'" />
                        <menu-outlined v-else-if="type === 'MENU'" />
                        <api-outlined v-else-if="type === 'API'" />
                        <control-outlined v-else-if="type === 'BUTTON'" />
                        <file-outlined v-else-if="type === 'PAGE'" />
                        <folder-outlined v-else />
                      </div>
                      <div style="display: flex; align-items: center; flex: 1">
                        <span class="node-name">{{ name }}</span>
                        <a-tag
                          v-if="type"
                          size="small"
                          class="node-type-tag inline-tag"
                          :color="getTypeColor(type)"
                        >
                          {{ getTypeLabel(type) }}
                        </a-tag>
                      </div>
                    </div>
                  </div>
                </template>
              </a-tree>

              <a-empty v-else description="暂无权限数据" class="empty-tree" />
            </div>
          </a-spin>
        </div>

        <!-- 右侧：权限详情 -->
        <div class="permission-detail-section">
          <div class="section-header">
            <h3 class="section-title">权限详情</h3>
          </div>

          <div class="detail-content">
            <a-empty
              v-if="!selectedNode"
              description="请选择权限节点查看详情"
              class="empty-detail"
            />

            <a-card v-else class="detail-card" :bordered="false">
              <template #title>
                <div class="detail-header">
                  <div
                    class="detail-icon"
                    :class="`icon-${selectedNode.type?.toLowerCase()}`"
                  >
                    <folder-open-outlined
                      v-if="selectedNode.type === 'DIRECTORY'"
                    />
                    <menu-outlined v-else-if="selectedNode.type === 'MENU'" />
                    <api-outlined v-else-if="selectedNode.type === 'API'" />
                    <control-outlined
                      v-else-if="selectedNode.type === 'BUTTON'"
                    />
                    <file-outlined v-else-if="selectedNode.type === 'PAGE'" />
                    <folder-outlined v-else />
                  </div>
                  <div
                    class="detail-title"
                    style="display: flex; align-items: center"
                  >
                    <h4 style="margin: 0; margin-right: 8px">
                      {{ selectedNode.name }}
                    </h4>
                    <a-tag
                      size="small"
                      class="type-tag inline-tag"
                      :color="getTypeColor(selectedNode.type)"
                    >
                      {{ getTypeLabel(selectedNode.type) }}
                    </a-tag>
                  </div>
                </div>
              </template>

              <a-descriptions :column="1" size="small" bordered>
                <a-descriptions-item label="权限编码">
                  {{ selectedNode.code }}
                </a-descriptions-item>

                <a-descriptions-item
                  v-if="selectedNode.parentCode"
                  label="父级编码"
                >
                  {{ selectedNode.parentCode }}
                </a-descriptions-item>

                <a-descriptions-item v-if="selectedNode.path" label="访问路径">
                  {{ selectedNode.path }}
                </a-descriptions-item>

                <a-descriptions-item
                  v-if="selectedNode.method"
                  label="请求方法"
                >
                  <a-tag size="small">{{ selectedNode.method }}</a-tag>
                </a-descriptions-item>

                <a-descriptions-item
                  v-if="selectedNode.permission"
                  label="权限标识"
                >
                  {{ selectedNode.permission }}
                </a-descriptions-item>

                <a-descriptions-item label="授权状态">
                  <a-tag
                    :color="
                      checkedKeys.includes(selectedNode.code)
                        ? 'success'
                        : 'default'
                    "
                  >
                    {{
                      checkedKeys.includes(selectedNode.code)
                        ? "已授权"
                        : "未授权"
                    }}
                  </a-tag>
                </a-descriptions-item>
              </a-descriptions>
            </a-card>
          </div>
        </div>
      </div>
    </div>
  </a-modal>
</template>

<script setup>
import { ref, watch } from "vue";
import { message } from "ant-design-vue";
import {
  FolderOpenOutlined,
  FolderOutlined,
  MenuOutlined,
  ApiOutlined,
  ControlOutlined,
  FileOutlined,
  CheckOutlined,
  CloseOutlined,
  FullscreenOutlined,
  FullscreenExitOutlined,
} from "@ant-design/icons-vue";
import { getResourceTree } from "@/api/resource";
import { getRoleResourceCodes, assignRoleResources } from "@/api/roleResource";

const props = defineProps({
  visible: {
    type: Boolean,
    default: false,
  },
  roleData: {
    type: Object,
    default: () => ({}),
  },
});

const emits = defineEmits(["update:visible", "success"]);

// 响应式数据
const loading = ref(false);
const treeLoading = ref(false);
const treeData = ref([]);
const checkedKeys = ref([]);
const expandedKeys = ref([]);
const selectedKeys = ref([]);
const selectedNode = ref(null);
const treeRef = ref(null);

// 资源类型配置
const RESOURCE_TYPE = {
  DIRECTORY: { label: "目录", color: "blue" },
  MENU: { label: "菜单", color: "blue" },
  BUTTON: { label: "按钮", color: "cyan" },
  API: { label: "接口", color: "purple" },
  PAGE: { label: "页面", color: "green" },
};

// 获取类型标签
const getTypeLabel = (type) => {
  return RESOURCE_TYPE[type]?.label || "未知";
};

// 获取类型颜色
const getTypeColor = (type) => {
  return RESOURCE_TYPE[type]?.color || "default";
};

// 计算总权限数量
const getTotalPermissionCount = () => {
  const countNodes = (nodes) => {
    let count = 0;
    nodes.forEach((node) => {
      count++;
      if (node.children && node.children.length > 0) {
        count += countNodes(node.children);
      }
    });
    return count;
  };
  return countNodes(treeData.value);
};

// 节点选择处理
const handleNodeSelect = (selectedKeysValue, { node }) => {
  if (selectedKeysValue.length > 0) {
    selectedNode.value = node;
  } else {
    selectedNode.value = null;
  }
};

// 处理权限勾选变化
const handleCheck = (checkedKeysValue, info) => {
  checkedKeys.value = checkedKeysValue;
};

// 展开全部
const expandAll = () => {
  const getAllKeys = (nodes) => {
    let keys = [];
    nodes.forEach((node) => {
      keys.push(node.code);
      if (node.children && node.children.length > 0) {
        keys = keys.concat(getAllKeys(node.children));
      }
    });
    return keys;
  };
  expandedKeys.value = getAllKeys(treeData.value);
};

// 收起全部
const collapseAll = () => {
  expandedKeys.value = [];
};

// 全选
const checkAll = () => {
  const getAllKeys = (nodes) => {
    let keys = [];
    nodes.forEach((node) => {
      keys.push(node.code);
      if (node.children && node.children.length > 0) {
        keys = keys.concat(getAllKeys(node.children));
      }
    });
    return keys;
  };
  checkedKeys.value = getAllKeys(treeData.value);
};

// 取消全选
const uncheckAll = () => {
  checkedKeys.value = [];
};

// 获取资源树数据
const fetchResourceTree = async () => {
  if (!props.roleData.appId) return;

  treeLoading.value = true;
  try {
    const res = await getResourceTree(props.roleData.appId);
    treeData.value = res.data || [];
  } catch (error) {
    message.error("获取资源树失败");
  } finally {
    treeLoading.value = false;
  }
};

// 获取角色已有权限
const fetchRolePermissions = async () => {
  if (!props.roleData.id) return;

  try {
    const res = await getRoleResourceCodes(props.roleData.id);
    checkedKeys.value = res.data || [];
  } catch (error) {
    message.error("获取角色权限失败");
  }
};

// 保存权限分配
const handleSave = async () => {
  loading.value = true;
  try {
    await assignRoleResources({
      roleId: props.roleData.id,
      applicationCode: props.roleData.applicationCode,
      resourceCodes: checkedKeys.value,
    });
    message.success("权限分配成功");
    emits("success");
    handleCancel();
  } catch (error) {
    message.error("权限分配失败");
  } finally {
    loading.value = false;
  }
};

// 取消
const handleCancel = () => {
  emits("update:visible", false);
};

// 监听弹窗显示状态
watch(
  () => props.visible,
  (newVal) => {
    if (newVal) {
      fetchResourceTree();
      fetchRolePermissions();
    }
  }
);
</script>

<style scoped>
.role-permission-container {
  padding: 0;
}

:deep(.ant-modal-content) {
  border-radius: 12px;
  overflow: hidden;
}

:deep(.ant-modal-header) {
  background: #f5f7fa;
  border-bottom: 1px solid #e8e8e8;
}

.permission-layout {
  display: flex;
  gap: 20px;
  height: 580px;
  align-items: stretch;
}

.system-list {
  width: 200px;
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  padding: 16px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
  height: auto;
  display: flex;
  flex-direction: column;
}

.section-title {
  margin: 0 0 12px 0;
  font-size: 16px;
  font-weight: 600;
  color: #000000;
}

.system-items {
  padding: 8px 0;
  font-size: 14px;
  font-weight: 500;
  color: #f98b8a;
  border-bottom: 1px solid #f0f0f0;
}

.system-items:last-child {
  border-bottom: none;
}

.permission-assignment {
  width: calc(100% - 500px);
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  padding: 16px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
  height: auto;
  overflow: hidden;
}

.permission-detail-section {
  width: 600px;
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: 8px;
  border: 1px solid #e8e8e8;
  padding: 16px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.02);
  height: auto;
}

.section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.title-icon {
  margin-right: 8px;
}

.permission-stats {
  display: flex;
  gap: 16px;
}

.stats-item {
  display: flex;
  align-items: center;
  gap: 4px;
}

.stats-label {
  font-size: 14px;
  color: #666;
}

.stats-value {
  font-size: 14px;
  font-weight: 600;
  color: #333;
}

.tree-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding: 8px 12px;
  background: #f5f5f5;
  border-radius: 6px;
}

.toolbar-left {
  display: flex;
  align-items: center;
}

.toolbar-label {
  font-size: 14px;
  color: #666;
  margin-right: 8px;
}

.tree-actions {
  display: flex;
  gap: 8px;
}

.action-btn {
  font-size: 12px;
}

.action-btn.check-all {
  background: #1890ff;
  border-color: #1890ff;
  color: white;
}

.action-btn.check-all:hover {
  background: #40a9ff;
  border-color: #40a9ff;
}

.action-btn.uncheck-all {
  background: white;
  border-color: #d9d9d9;
  color: #666;
}

.tree-container {
  height: 450px;
  border: 1px solid #f0f0f0;
  padding: 16px;
  border-radius: 8px;
  background-color: #fafafa;
  overflow: auto;
  margin-bottom: 0;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
  display: flex;
  flex-direction: column;
}

.permission-tree {
  flex: 1;
  overflow: auto;
}

:deep(.ant-tree-treenode) {
  padding: 0;
  transition: background-color 0.3s;
  border-radius: 6px;
  margin: 1px 0;
  height: 24px;
  line-height: 24px;
  display: flex;
  align-items: center;

  &:hover {
    background-color: #f0f7ff;
  }

  &.ant-tree-treenode-selected {
    background-color: #e6f7ff !important;
    border-left: 3px solid #1890ff !important;
    padding-left: 0 !important; /* 修复左边框导致的偏移 */
    margin-left: -3px !important; /* 补偿左边框宽度 */

    .ant-tree-node-content-wrapper {
      color: #333 !important;
    }

    .tree-node {
      .node-content {
        .node-icon {
          color: inherit !important;
        }

        .node-name {
          color: #333 !important;
          font-weight: 600 !important;
        }

        .node-type-tag {
          background-color: rgba(24, 144, 255, 0.1) !important;
          color: #1890ff !important;
          border-color: rgba(24, 144, 255, 0.2) !important;
        }
      }
    }
  }
}

:deep(.ant-tree-checkbox) {
  margin-right: 8px;
  vertical-align: middle;
  margin-top: 0;
}

:deep(.ant-tree-node-content-wrapper) {
  transition: background-color 0.3s;
  padding: 0 2px;
  display: inline-flex;
  align-items: center;
  vertical-align: middle;

  &:hover {
    background-color: transparent;
  }

  &.ant-tree-node-selected {
    background-color: transparent;
  }
}

:deep(.ant-tree-switcher) {
  transition: all 0.3s;
  line-height: 1;
  width: 20px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  vertical-align: middle;
  margin-top: 0;
  padding-right: 0;

  &:hover {
    background-color: #e6f7ff;
    border-radius: 4px;
  }

  .ant-tree-switcher-icon {
    font-size: 12px;
    color: #1890ff;
    display: flex;
    align-items: center;
    justify-content: center;
  }
}

:deep(.ant-tree-indent-unit) {
  width: 16px;
  height: 24px;
  line-height: 24px;
  vertical-align: middle;
}

.tree-node {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 0;
  cursor: pointer;
  transition: all 0.2s;
  height: 24px;
  line-height: 24px;

  &:hover {
    transform: translateX(2px);
  }
}

.node-content {
  display: flex;
  align-items: center;
}

.node-icon {
  margin-right: 4px;
  font-size: 16px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 24px;
  border-radius: 4px;
  transition: all 0.3s;
  vertical-align: middle;
}

.icon-directory {
  color: #1890ff;
}

.icon-menu {
  color: #52c41a;
}

.icon-api {
  color: #722ed1;
}

.icon-button {
  color: #fa8c16;
}

.icon-page {
  color: #13c2c2;
}

.node-name {
  display: inline-block;
  font-weight: 500;
  font-size: 14px;
  color: #333;
  vertical-align: middle;
}

.node-type-tag {
  font-size: 11px;
  line-height: 16px;
  height: 18px;
  padding: 0 4px;
  margin-right: 0;
  margin-left: 4px;
  border-radius: 10px;
  border: none;
}

.inline-tag {
  margin-left: 4px;
  vertical-align: middle;
  display: inline-flex;
  align-items: center;
  height: 18px;
  line-height: 18px;
}

.empty-tree {
  height: 200px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.detail-content {
  flex: 1;
  overflow: auto;
  display: flex;
  flex-direction: column;
}

.empty-detail {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.detail-card {
  flex: 1;
  border-radius: 8px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03);
  display: flex;
  flex-direction: column;
}

:deep(.ant-card-head) {
  padding: 0;
  min-height: auto;
  border-bottom: 1px solid #f0f0f0;
}

:deep(.ant-card-body) {
  padding: 16px;
  flex: 1;
  overflow: auto;
}

:deep(.ant-descriptions-bordered .ant-descriptions-item-label) {
  background-color: #fafafa;
  font-weight: 500;
}

:deep(.ant-descriptions-bordered) {
  border-radius: 8px;
  overflow: hidden;
}

.detail-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px;
}

.detail-icon {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  background: #f5f7fa;
  font-size: 16px;
}

.detail-title {
  display: flex;
  align-items: center;
  gap: 8px;
}

.type-tag {
  border: none;
  border-radius: 10px;
  padding: 0 6px;
  line-height: 16px;
  height: 18px;
  font-size: 11px;
}
</style>
